package rexsee.natives;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import rexsee.core.animation.AnimationStyleSheet;
import rexsee.core.browser.Browser;
import rexsee.core.browser.BrowserDiv;
import rexsee.core.browser.RexseeUrl;
import rexsee.core.browser.clazz.JavascriptInterface;
import rexsee.core.browser.clazz.LogListeners.LogListener;
import rexsee.core.lang.RexseeLanguage;
import rexsee.core.style.CanvasSheet;
import rexsee.core.style.RexseeDrawable;
import rexsee.core.utilities.Json;
import rexsee.core.utilities.Utilities;
import rexsee.core.widget.Div;
import rexsee.ebook.PageView;
import rexsee.multimedia.VideoView;
import rexsee.natives.ViewParser.ViewItem;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.text.Html;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.Chronometer;
import android.widget.DatePicker;
import android.widget.FrameLayout;
import android.widget.Gallery;
import android.widget.GridView;
import android.widget.HorizontalScrollView;
import android.widget.ImageSwitcher;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RatingBar;
import android.widget.ScrollView;
import android.widget.Spinner;
import android.widget.TableLayout;
import android.widget.TextSwitcher;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.ToggleButton;
import android.widget.ViewAnimator;
import android.widget.ViewFlipper;
import android.widget.ViewSwitcher;

public class RexseeJavaView implements JavascriptInterface {

	public static final String INTERFACE_NAME = "JavaView";
	@Override
	public String getInterfaceName() {
		return mBrowser.application.resources.prefix + INTERFACE_NAME;
	}
	@Override
	public JavascriptInterface getInheritInterface(Browser childBrowser) {
		return this;
	}
	@Override
	public JavascriptInterface getNewInterface(Browser childBrowser) {
		return this;
	}

	public static final int SYNC_CYCLE = 10;

	public static final String EVENT_ONJAVAVIEWTOUCHDOWN = "onJavaViewTouchDown";
	public static final String EVENT_ONJAVAVIEWTOUCHUP = "onJavaViewTouchUp";
	public static final String EVENT_ONJAVAVIEWTOUCHCANCEL = "onJavaViewTouchCancel";
	public static final String EVENT_ONJAVAVIEWTOUCHMOVE = "onJavaViewTouchMove";
	public static final String EVENT_ONJAVAVIEWTOUCHSCROLL = "onJavaViewTouchScroll";
	public static final String EVENT_ONJAVAVIEWCLICK = "onJavaViewClick";
	public static final String EVENT_ONJAVAVIEWDOUBLECLICK = "onJavaViewDoubleClick";
	public static final String EVENT_ONJAVAVIEWLONGPRESS = "onJavaViewLongPress";
	public static final String EVENT_ONJAVAVIEWFLING = "onJavaViewFling";
	public static final String EVENT_ONJAVAVIEWSCROLL = "onJavaViewScroll";

	public static final String EVENT_ONZOOMCONTROLPRESSED = "onJavaZoomControlPressed";
	public static final String EVENT_ONITEMCLICKED = "onJavaItemClicked";
	public static final String EVENT_ONITEMLONGCLICKED = "onJavaItemLongClicked";

	public static final String EVENT_ONEDITTEXTCHANGED = "onJavaEditTextChanged";
	public static final String EVENT_ONSEEKBARCHANGED = "onJavaSeekBarChanged";
	public static final String EVENT_ONRATINGBARCHANGED = "onJavaRatingBarChanged";
	public static final String EVENT_ONDATEPICKERCHANGED = "onJavaDatePickerChanged";
	public static final String EVENT_ONTIMEPICKERCHANGED = "onJavaTimePickerChanged";
	public static final String EVENT_ONSPINNERCHANGED = "onJavaSpinnerChanged";
	public static final String EVENT_ONGALLERYCHANGED = "onJavaGalleryChanged";
	public static final String EVENT_ONSLIDINGDRAWERCHANGED = "onJavaSlidingDrawerChanged";
	public static final String EVENT_ONCHRONOMETERCHANGED = "onJavaChronometerChanged";
	public static final String EVENT_ONVIDEVIEWCHANGED = "onJavaVideoViewChanged";
	public static final String EVENT_ONSURFACECHANGED = "onJavaSurfaceChanged";

	private final Browser mBrowser;
	private final Context mContext;
	private final HashMap<String, ViewTag> mMap;
	private int mUniqueId = 0;
	private boolean syncTag = false;
	private void syncRunOnUiThread(final Runnable runnable) {
		syncTag = false;
		((Activity) mContext).runOnUiThread(new Runnable() {
			@Override
			public void run() {
				try {
					runnable.run();
				} catch (Exception e) {
					mBrowser.exception(getInterfaceName(), e);
				}
				syncTag = true;
			}
		});
		while (!syncTag) {
			try {
				Thread.sleep(SYNC_CYCLE);
			} catch (Exception e) {

			}
		}
	}

	public RexseeJavaView(Browser browser) {

		super();
		mBrowser = browser;
		mContext = browser.getContext();
		mMap = new HashMap<String, ViewTag>();

		mBrowser.eventList.add(EVENT_ONJAVAVIEWTOUCHDOWN);
		mBrowser.eventList.add(EVENT_ONJAVAVIEWTOUCHUP);
		mBrowser.eventList.add(EVENT_ONJAVAVIEWTOUCHCANCEL);
		mBrowser.eventList.add(EVENT_ONJAVAVIEWTOUCHMOVE);
		mBrowser.eventList.add(EVENT_ONJAVAVIEWCLICK);
		mBrowser.eventList.add(EVENT_ONJAVAVIEWDOUBLECLICK);
		mBrowser.eventList.add(EVENT_ONJAVAVIEWLONGPRESS);
		mBrowser.eventList.add(EVENT_ONJAVAVIEWFLING);
		mBrowser.eventList.add(EVENT_ONJAVAVIEWTOUCHSCROLL);
		mBrowser.eventList.add(EVENT_ONJAVAVIEWSCROLL);

		mBrowser.eventList.add(EVENT_ONEDITTEXTCHANGED);
		mBrowser.eventList.add(EVENT_ONSPINNERCHANGED);
		mBrowser.eventList.add(EVENT_ONGALLERYCHANGED);
		mBrowser.eventList.add(EVENT_ONSLIDINGDRAWERCHANGED);
		mBrowser.eventList.add(EVENT_ONSEEKBARCHANGED);
		mBrowser.eventList.add(EVENT_ONRATINGBARCHANGED);
		mBrowser.eventList.add(EVENT_ONDATEPICKERCHANGED);
		mBrowser.eventList.add(EVENT_ONTIMEPICKERCHANGED);
		mBrowser.eventList.add(EVENT_ONCHRONOMETERCHANGED);
		mBrowser.eventList.add(EVENT_ONZOOMCONTROLPRESSED);
		mBrowser.eventList.add(EVENT_ONITEMCLICKED);
		mBrowser.eventList.add(EVENT_ONITEMLONGCLICKED);
		mBrowser.eventList.add(EVENT_ONVIDEVIEWCHANGED);
		mBrowser.eventList.add(EVENT_ONSURFACECHANGED);

	}

	public ViewTag getViewTag(String id) {
		return mMap.get(id);
	}
	public View getView(String id) {
		ViewTag viewTag = mMap.get(id);
		return (viewTag == null) ? null : viewTag.view;
	}
	public int getViewUniqueId(String id) {
		ViewTag viewTag = mMap.get(id);
		return (viewTag == null) ? -1 : viewTag.view.getId();
	}

	private void _setChilds(ViewTag viewTag, String childs) {
		if (viewTag.type.equalsIgnoreCase("PageView")) {
			int position = Utilities.getInt(viewTag.style.progress, 0);
			((PageView) viewTag.view).load(childs, position);
			return;
		}
		String[] ids = childs.split("\\|");
		if (viewTag.type.equalsIgnoreCase("Spinner")) {
			((Spinner) viewTag.view).setAdapter(new StringAdapter(mBrowser, viewTag.style, ids));
			((Spinner) viewTag.view).setSelection(0);
		} else if (viewTag.type.equalsIgnoreCase("Gallery") || viewTag.type.equalsIgnoreCase("ThreeDGallery")) {
			if (viewTag.style.mode.equalsIgnoreCase("View")) {
				View[] views = new View[ids.length];
				for (int i = 0; i < ids.length; i++) {
					ViewTag childTag = mMap.get(ids[i]);
					views[i] = childTag.view;
					childTag.parentId = viewTag.id;
					viewTag.childIds.add(childTag.id);
				}
				((Gallery) viewTag.view).setAdapter(new GalleryAdapter(mBrowser, viewTag, views));
				((Gallery) viewTag.view).setSelection(0);
			} else {
				((Gallery) viewTag.view).setAdapter(new GalleryAdapter(mBrowser, viewTag, ids));
				((Gallery) viewTag.view).setSelection(0);
			}
		} else if (viewTag.type.equalsIgnoreCase("ListView")) {
			if (viewTag.style.mode.equalsIgnoreCase("View")) {
				View[] views = new View[ids.length];
				for (int i = 0; i < ids.length; i++) {
					ViewTag childTag = mMap.get(ids[i]);
					views[i] = childTag.view;
					childTag.parentId = viewTag.id;
					viewTag.childIds.add(childTag.id);
				}
				((ListView) viewTag.view).setAdapter(new ListViewAdapter(mBrowser, viewTag, views));
			} else if (viewTag.style.mode.equalsIgnoreCase("Drawable")) {
				((ListView) viewTag.view).setAdapter(new ListViewAdapter(mBrowser, viewTag, ids));
			} else {
				((ListView) viewTag.view).setAdapter(new StringAdapter(mBrowser, viewTag.style, ids));
			}
		} else if (viewTag.type.equalsIgnoreCase("GridView")) {
			if (viewTag.style.mode.equalsIgnoreCase("View")) {
				View[] views = new View[ids.length];
				for (int i = 0; i < ids.length; i++) {
					ViewTag childTag = mMap.get(ids[i]);
					views[i] = childTag.view;
					childTag.parentId = viewTag.id;
					viewTag.childIds.add(childTag.id);
				}
				((GridView) viewTag.view).setAdapter(new ListViewAdapter(mBrowser, viewTag, views));
			} else if (viewTag.style.mode.equalsIgnoreCase("Drawable")) {
				((GridView) viewTag.view).setAdapter(new ListViewAdapter(mBrowser, viewTag, ids));
			} else {
				((GridView) viewTag.view).setAdapter(new StringAdapter(mBrowser, viewTag.style, ids));
			}
		} else if (viewTag.type.equalsIgnoreCase("SlidingDrawer")) {
			ViewTag handleTag = mMap.get(ids[0]);
			ViewTag contentTag = mMap.get(ids[1]);
			FrameLayout handle = ((SlidingDrawer) viewTag.view).getHandle();
			handle.removeAllViews();
			handle.addView(handleTag.view);
			FrameLayout content = ((SlidingDrawer) viewTag.view).getContent();
			content.removeAllViews();
			content.addView(contentTag.view);
			handleTag.parentId = viewTag.id;
			contentTag.parentId = viewTag.id;
			viewTag.childIds.add(handleTag.id);
			viewTag.childIds.add(contentTag.id);
		} else if (viewTag.type.equalsIgnoreCase("Div")) {
			for (int i = 0; i < ids.length; i++) {
				ViewTag childTag = mMap.get(ids[i]);
				int index = Utilities.getInt(childTag.style.index, -1);
				if (index >= 0) ((Div) viewTag.view).innerLayout.addView(childTag.view, index);
				else ((Div) viewTag.view).innerLayout.addView(childTag.view);
				childTag.parentId = viewTag.id;
				viewTag.childIds.add(childTag.id);
			}
		} else if (viewTag.type.equalsIgnoreCase("ViewSwitcher")) {
			if (viewTag.childIds.size() > 0) {
				ViewTag oldChild = mMap.get(viewTag.childIds.get(0));
				oldChild.parentId = null;
				viewTag.childIds.clear();
			}
			final ViewTag childTag = mMap.get(ids[0]);
			if (childTag == null || childTag.view == null) return;
			FrameLayout next = (FrameLayout) ((ViewSwitcher) viewTag.view).getNextView();
			next.removeAllViews();
			next.addView(childTag.view);
			childTag.parentId = viewTag.id;
			viewTag.childIds.add(childTag.id);
			((ViewSwitcher) viewTag.view).showNext();
		} else {
			for (int i = 0; i < ids.length; i++) {
				ViewTag childTag = mMap.get(ids[i]);
				int index = Utilities.getInt(childTag.style.index, -1);
				if (index >= 0) ((ViewGroup) viewTag.view).addView(childTag.view, index);
				else ((ViewGroup) viewTag.view).addView(childTag.view);
				childTag.parentId = viewTag.id;
				viewTag.childIds.add(childTag.id);
			}
		}
	}

	private void _createFromXml(String xml) {
		ViewParser parser = new ViewParser(mBrowser, new LogListener() {
			@Override
			public void run(Context context, Browser browser, int type, String message) {
				mBrowser.exception(this.getClass().getName(), message);
			}
		}, xml);
		if (parser.items == null || parser.items.size() == 0) {
			mBrowser.exception(RexseeUrl.class.getName() + "._createFromXml", "No item parsed.");
			return;
		}
		for (int i = 0; i < parser.items.size(); i++) {
			ViewItem item = parser.items.get(i);
			if (item.isNull()) continue;
			ViewTag viewTag = ViewStyle.create(mBrowser, item.id, mUniqueId++, item.type, item.style, RexseeJavaView.this);
			if (viewTag == null) continue;
			mMap.put(item.id, viewTag);
		}
		for (int i = 0; i < parser.items.size(); i++) {
			ViewItem item = parser.items.get(i);
			if (item.isNull() || !item.hasChild()) continue;
			ViewTag viewTag = mMap.get(item.id);
			if (viewTag == null || viewTag.view == null || !viewTag.canHaveChild) continue;
			_setChilds(viewTag, item.childs);
		}
	}

	//JavaScript Interface

	public void create(final String xml) {
		if (xml == null) {
			mBrowser.exception(this.getClass().getSimpleName(), "Null XML content.");
			return;
		}
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				mBrowser.progressDialog.show(RexseeLanguage.PROGRESS_ONGOING);
				_createFromXml(xml);
				mBrowser.progressDialog.hide();
			}
		});
	}
	public void create(String xmlFile, final String xmlEncoding) {
		if (xmlFile == null) {
			mBrowser.exception(this.getClass().getSimpleName(), "Null XML file.");
			return;
		}
		final String url = mBrowser.urlListeners.getAbsoluteUrl(xmlFile).trim();
		final String encoding = (xmlEncoding == null) ? "UTF-8" : xmlEncoding;
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				mBrowser.progressDialog.show(RexseeLanguage.PROGRESS_ONGOING);
				try {
					String xml;
					if (url.toLowerCase().startsWith("http://") || url.toLowerCase().startsWith("https://")) {
						xml = Utilities.getContent(mBrowser.getContext(), url, new LogListener() {
							@Override
							public void run(Context context, Browser browser, int type, String message) {
								mBrowser.exception(RexseeUrl.class.getName() + ".getContent", message);
							}
						}, encoding);
					} else if (url.toLowerCase().startsWith(RexseeUrl.ASSET_URL)) {
						xml = new String(Utilities.getAssetContent(mContext, url), encoding);
					} else if (url.toLowerCase().startsWith("file://")) {
						xml = new String(Utilities.getContent(url), encoding);
					} else {
						mBrowser.exception(this.getClass().getSimpleName(), "Invalide xmlFile: " + url);
						mBrowser.progressDialog.hide();
						return;
					}
					if (xml == null) {
						mBrowser.exception(this.getClass().getSimpleName(), "Xml is null: " + url);
						mBrowser.progressDialog.hide();
						return;
					}
					_createFromXml(xml);
					mBrowser.progressDialog.hide();
				} catch (Exception e) {
					mBrowser.exception(this.getClass().getSimpleName(), e.getLocalizedMessage());
					mBrowser.progressDialog.hide();
					return;
				}
			}
		});
	}
	public void create(final String id, final String type, final String style) {
		if (id == null || id.trim().equalsIgnoreCase("") || mMap.containsKey(id)) {
			mBrowser.exception(this.getClass().getSimpleName(), "Null ID or ID duplicated.");
			return;
		}
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				ViewTag viewTag = ViewStyle.create(mBrowser, id, mUniqueId++, type, style, RexseeJavaView.this);
				if (viewTag == null) {
					mBrowser.exception(this.getClass().getSimpleName(), "Invalid view type.");
					return;
				}
				mMap.put(id, viewTag);
			}
		});
	}
	public void destroy(String id) {
		if (!mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag != null && viewTag.parentId != null) {
			removeChild(viewTag.parentId, id);
		}
		if (viewTag.view.getParent() != null) {
			syncRunOnUiThread(new Runnable() {
				@Override
				public void run() {
					((ViewGroup) viewTag.view.getParent()).removeView(viewTag.view);
				}
			});
		}
		removeChilds(id);
		if (viewTag.type.equalsIgnoreCase("PageView")) {
			((PageView) viewTag.view).destroy();
		} else if (viewTag.type.equalsIgnoreCase("WebView") || viewTag.type.equalsIgnoreCase("Browser") || viewTag.type.equalsIgnoreCase("BrowserDiv")) {
			try {
				((BrowserDiv) viewTag.view).browser.onDestroy();
			} catch (Exception e) {
				mBrowser.exception(getInterfaceName(), e.getLocalizedMessage());
			}
		}
		mMap.remove(id);
		System.gc();
	}
	public void destroyAll() {
		if (mMap.size() == 0) return;
		Set<String> ids = mMap.keySet();
		Iterator<String> iterator = ids.iterator();
		while (iterator.hasNext()) {
			String id = iterator.next();
			final ViewTag viewTag = mMap.get(id);
			if (viewTag != null && viewTag.parentId != null) {
				removeChild(viewTag.parentId, id);
			}
			if (viewTag.view.getParent() != null) {
				syncRunOnUiThread(new Runnable() {
					@Override
					public void run() {
						((ViewGroup) viewTag.view.getParent()).removeView(viewTag.view);
					}
				});
			}
			removeChilds(id);
			if (viewTag.type.equalsIgnoreCase("PageView")) {
				((PageView) viewTag.view).destroy();
			} else if (viewTag.type.equalsIgnoreCase("WebView") || viewTag.type.equalsIgnoreCase("Browser") || viewTag.type.equalsIgnoreCase("BrowserDiv")) {
				try {
					((BrowserDiv) viewTag.view).browser.onDestroy();
				} catch (Exception e) {
					mBrowser.exception(getInterfaceName(), e.getLocalizedMessage());
				}
			}
		}
		mMap.clear();
		System.gc();
	}
	public boolean exists(String id) {
		return mMap.containsKey(id);
	}
	public int size() {
		return mMap.size();
	}
	public String getIds() {
		String rtn = "";
		Set<String> ids = mMap.keySet();
		Iterator<String> iterator = ids.iterator();
		while (iterator.hasNext()) {
			if (!rtn.equals("")) rtn += ",";
			rtn += "\"" + iterator.next() + "\"";
		}
		return "[" + rtn + "]";
	}
	public boolean hasParent(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return false;
		ViewTag viewTag = mMap.get(id);
		return viewTag.view.getParent() != null;
	}
	public String getParent(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return "";
		ViewTag viewTag = mMap.get(id);
		return (viewTag.parentId == null) ? "" : viewTag.parentId;
	}
	public void setChilds(String id, final String childs) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return;
		if (!viewTag.canHaveChild) {
			mBrowser.exception(getInterfaceName(), "Can not set: the specified view can not have child!");
			return;
		}
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				_setChilds(viewTag, childs);
				viewTag.view.postInvalidate();
			}
		});
	}
	public void removeChild(String id, String childId) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null || !viewTag.canHaveChild) return;
		ViewTag childTag;
		if (childId == null || childId.trim().equals("")) {
			for (int i = 0; i < viewTag.childIds.size(); i++) {
				try {
					mMap.get(viewTag.childIds.get(i)).parentId = null;
				} catch (Exception e) {
				}
			}
			viewTag.childIds.clear();
			childTag = null;
		} else {
			childTag = mMap.get(childId);
			if (childTag != null) childTag.parentId = null;
			viewTag.childIds.remove(childId);
		}
		final ViewTag cTag = childTag;
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				if (viewTag.type.equalsIgnoreCase("Spinner")) {
					((Spinner) viewTag.view).setAdapter(null);
				} else if (viewTag.type.equalsIgnoreCase("Gallery") || viewTag.type.equalsIgnoreCase("ThreeDGallery")) {
					((Gallery) viewTag.view).setAdapter(null);
				} else if (viewTag.type.equalsIgnoreCase("ListView")) {
					((ListView) viewTag.view).setAdapter(null);
				} else if (viewTag.type.equalsIgnoreCase("GridView")) {
					((GridView) viewTag.view).setAdapter(null);
				} else if (viewTag.type.equalsIgnoreCase("SlidingDrawer")) {
					((SlidingDrawer) viewTag.view).getHandle().removeAllViews();
					((SlidingDrawer) viewTag.view).getContent().removeAllViews();
				} else if (viewTag.type.equalsIgnoreCase("Div")) {
					if (cTag != null) {
						((Div) viewTag.view).innerLayout.removeView(cTag.view);
					} else {
						((Div) viewTag.view).innerLayout.removeAllViews();
					}
				} else if (viewTag.type.equalsIgnoreCase("ViewSwitcher")) {
					((FrameLayout) ((ViewSwitcher) viewTag.view).getCurrentView()).removeAllViews();
					((FrameLayout) ((ViewSwitcher) viewTag.view).getNextView()).removeAllViews();
				} else if (viewTag.type.equalsIgnoreCase("PageView")) {
					((PageView) viewTag.view).clear();
				} else {
					if (cTag != null) {
						((ViewGroup) viewTag.view).removeView(cTag.view);
					} else {
						((ViewGroup) viewTag.view).removeAllViews();
					}
				}
			}
		});
	}
	public void removeChilds(String id) {
		removeChild(id, null);
	}
	public String getChilds(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return "[]";
		return Json.toJson(mMap.get(id).childIds);
	}
	public int countChilds(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return 0;
		return mMap.get(id).childIds.size();
	}
	public void bringToFront(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return;
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				viewTag.view.bringToFront();
				viewTag.view.invalidate();
			}
		});
	}
	public String getRect(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return "{}";
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return "{}";
		String rtn = "";
		rtn += "\"top\":" + viewTag.view.getTop();
		rtn += ",\"bottom\":" + viewTag.view.getBottom();
		rtn += ",\"left\":" + viewTag.view.getLeft();
		rtn += ",\"right\":" + viewTag.view.getRight();
		rtn += ",\"width\":" + (viewTag.view.getRight() - viewTag.view.getLeft());
		rtn += ",\"height\":" + (viewTag.view.getBottom() - viewTag.view.getTop());
		return "{" + rtn + "}";
	}
	public String getType(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return "";
		return mMap.get(id).type;
	}
	public void setStyle(final String id, final String style) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null || viewTag.style == null) return;
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				ViewStyle.setStyle(mBrowser, viewTag, style, RexseeJavaView.this);
			}
		});
	}
	public String getStyle(String id, String name) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return "";
		if (name == null || name.trim().equalsIgnoreCase("")) return "";
		ViewTag viewTag = mMap.get(id);
		if (name.equalsIgnoreCase("width")) {
			return String.valueOf(viewTag.view.getWidth());
		} else if (name.equalsIgnoreCase("height")) {
			return String.valueOf(viewTag.view.getHeight());
		} else {
			String value = viewTag.style.getStyle(name);
			return (value == null) ? "null" : value;
		}
	}
	public void setSize(String id, final int width, final int height) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null || viewTag.style == null) return;
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				try {
					viewTag.view.setLayoutParams(new ViewGroup.LayoutParams(width, height));
				} catch (Exception e) {
				}
			}
		});
	}

	//Scroll
	public void scrollTo(String id, final int x, final int y) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return;
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				if (viewTag.type.equalsIgnoreCase("ScrollView")) {
					((ScrollView) viewTag.view).smoothScrollTo(x, y);
				} else if (viewTag.type.equalsIgnoreCase("HorizontalScrollView")) {
					((HorizontalScrollView) viewTag.view).smoothScrollTo(x, y);
				} else {
					viewTag.view.scrollTo(x, y);
				}
			}
		});
	}
	public void scrollBy(String id, final int x, final int y) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return;
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				if (viewTag.type.equalsIgnoreCase("ScrollView")) {
					((ScrollView) viewTag.view).smoothScrollBy(x, y);
				} else if (viewTag.type.equalsIgnoreCase("HorizontalScrollView")) {
					((HorizontalScrollView) viewTag.view).smoothScrollBy(x, y);
				} else {
					viewTag.view.scrollBy(x, y);
				}
			}
		});
	}
	public void scrollHome(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return;
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				if (viewTag.type.equalsIgnoreCase("ScrollView")) {
					((ScrollView) viewTag.view).fullScroll(View.FOCUS_UP);
				} else if (viewTag.type.equalsIgnoreCase("HorizontalScrollView")) {
					((HorizontalScrollView) viewTag.view).fullScroll(View.FOCUS_LEFT);
				} else if (viewTag.type.equalsIgnoreCase("PageView")) {
					((PageView) viewTag.view).setPageIndex(0);
				}
			}
		});
	}
	public void scrollEnd(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return;
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				if (viewTag.type.equalsIgnoreCase("ScrollView")) {
					((ScrollView) viewTag.view).fullScroll(View.FOCUS_DOWN);
				} else if (viewTag.type.equalsIgnoreCase("HorizontalScrollView")) {
					((HorizontalScrollView) viewTag.view).fullScroll(View.FOCUS_RIGHT);
				} else if (viewTag.type.equalsIgnoreCase("PageView")) {
					((PageView) viewTag.view).setPageIndex(((PageView) viewTag.view).getPageTotal() - 1);
				}
			}
		});
	}
	public void fling(String id, final int velocity) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return;
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				if (viewTag.type.equalsIgnoreCase("ScrollView")) {
					((ScrollView) viewTag.view).fling(velocity);
				} else if (viewTag.type.equalsIgnoreCase("HorizontalScrollView")) {
					((HorizontalScrollView) viewTag.view).fling(velocity);
				} else if (viewTag.type.equalsIgnoreCase("Gallery") || viewTag.type.equalsIgnoreCase("ThreeDGallery")) {
					((Gallery) viewTag.view).onFling(null, null, velocity, 0);
				}
			}
		});
	}
	public String getScrollPosition(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return "{}";
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return "{}";
		String rtn = "";
		rtn += "\"x\":" + viewTag.view.getScrollX();
		rtn += ",\"y\":" + viewTag.view.getScrollY();
		return "{" + rtn + "}";
	}
	public void showPrevious(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return;
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				if (viewTag.type.equalsIgnoreCase("ScrollView")) {
					((ScrollView) viewTag.view).pageScroll(View.FOCUS_UP);
				} else if (viewTag.type.equalsIgnoreCase("HorizontalScrollView")) {
					((HorizontalScrollView) viewTag.view).pageScroll(View.FOCUS_LEFT);
				} else if (viewTag.type.equalsIgnoreCase("ViewAnimator") || viewTag.type.equalsIgnoreCase("ViewFlipper")) {
					((ViewAnimator) viewTag.view).showPrevious();
				} else if (viewTag.type.equalsIgnoreCase("Gallery") || viewTag.type.equalsIgnoreCase("ThreeDGallery")) {
					((Gallery) viewTag.view).onKeyDown(KeyEvent.KEYCODE_DPAD_LEFT, null);
					((Gallery) viewTag.view).onKeyUp(KeyEvent.KEYCODE_DPAD_LEFT, null);
				} else if (viewTag.type.equalsIgnoreCase("PageView")) {
					((PageView) viewTag.view).setPageIndex(((PageView) viewTag.view).getPageIndex() - 1);
				}

			}
		});
	}
	public void showNext(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return;
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				if (viewTag.type.equalsIgnoreCase("ScrollView")) {
					((ScrollView) viewTag.view).pageScroll(View.FOCUS_DOWN);
				} else if (viewTag.type.equalsIgnoreCase("HorizontalScrollView")) {
					((HorizontalScrollView) viewTag.view).pageScroll(View.FOCUS_RIGHT);
				} else if (viewTag.type.equalsIgnoreCase("ViewAnimator") || viewTag.type.equalsIgnoreCase("ViewFlipper")) {
					((ViewAnimator) viewTag.view).showNext();
				} else if (viewTag.type.equalsIgnoreCase("Gallery") || viewTag.type.equalsIgnoreCase("ThreeDGallery")) {
					((Gallery) viewTag.view).onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null);
					((Gallery) viewTag.view).onKeyUp(KeyEvent.KEYCODE_DPAD_RIGHT, null);
				} else if (viewTag.type.equalsIgnoreCase("PageView")) {
					((PageView) viewTag.view).setPageIndex(((PageView) viewTag.view).getPageIndex() + 1);
				}

			}
		});
	}

	//Other
	public void requestFocus(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return;
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				viewTag.view.requestFocus();
			}
		});
	}
	public void clearFocus(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return;
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				viewTag.view.clearFocus();
			}
		});
	}

	public void setValue(final String id, final String setvalue) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return;
		final String value = setvalue.trim();
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				if (viewTag.type.equalsIgnoreCase("TextView") || viewTag.type.equalsIgnoreCase("EditText")) {
					setStyle(id, "label:" + value + ";");
				} else if (viewTag.type.equalsIgnoreCase("Chronometer")) {
					setStyle(id, "duration:" + value + ";");
				} else if (viewTag.type.equalsIgnoreCase("ProgressDiv") || viewTag.type.equalsIgnoreCase("Progress")) {
					setStyle(id, "progress:" + value + ";");
				} else if (viewTag.type.equalsIgnoreCase("ToggleButton")) {
					((ToggleButton) viewTag.view).setChecked(value.equalsIgnoreCase("true") || value.equalsIgnoreCase("checked") || value.equalsIgnoreCase("selected") || value.equals("1"));
				} else if (viewTag.type.equalsIgnoreCase("ProgressBar") || viewTag.type.equalsIgnoreCase("SeekBar")) {
					setStyle(id, "progress:" + value + ";");
				} else if (viewTag.type.equalsIgnoreCase("RatingBar")) {
					float rating = Utilities.getFloat(value, 0);
					((RatingBar) viewTag.view).setRating(rating);
				} else if (viewTag.type.equalsIgnoreCase("RadioGroup")) {
				} else if (viewTag.type.equalsIgnoreCase("CheckBox")) {
					((CheckBox) viewTag.view).setChecked(value.equalsIgnoreCase("true") || value.equalsIgnoreCase("checked") || value.equalsIgnoreCase("selected") || value.equals("1"));
				} else if (viewTag.type.equalsIgnoreCase("RadioButton")) {
					if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("checked") || value.equalsIgnoreCase("selected") || value.equals("1")) ((RadioButton) viewTag.view).toggle();
				} else if (viewTag.type.equalsIgnoreCase("Spinner")) {
					int position = Utilities.getInt(value, 0);
					if (position >= 0) ((Spinner) viewTag.view).setSelection(position, true);
				} else if (viewTag.type.equalsIgnoreCase("Gallery") || viewTag.type.equalsIgnoreCase("ThreeDGallery")) {
					int position = Utilities.getInt(value, 0);
					if (position >= 0) ((Gallery) viewTag.view).setSelection(position, true);
				} else if (viewTag.type.equalsIgnoreCase("DatePicker")) {
					String[] argu = value.split("-");
					if (argu.length == 3) {
						((DatePicker) viewTag.view).updateDate(Utilities.getInt(argu[0], 0), Utilities.getInt(argu[1], 1) - 1, Utilities.getInt(argu[2], 0));
					}
				} else if (viewTag.type.equalsIgnoreCase("TimePicker")) {
					String[] argu = value.split(":");
					if (argu.length == 2) {
						((TimePicker) viewTag.view).setCurrentHour(Utilities.getInt(argu[0], 0));
						((TimePicker) viewTag.view).setCurrentMinute(Utilities.getInt(argu[1], 0));
					}
				} else if (viewTag.type.equalsIgnoreCase("ViewAnimator")) {
					String cid = ((ViewTag) ((ViewAnimator) viewTag.view).getCurrentView().getTag()).id;
					if (cid.equals(value)) return;
					((ViewAnimator) viewTag.view).showNext();
					while (true) {
						String nid = ((ViewTag) ((ViewAnimator) viewTag.view).getCurrentView().getTag()).id;
						if (nid.equals(value) || nid.equals(cid)) break;
						((ViewAnimator) viewTag.view).showNext();
					}
				} else if (viewTag.type.equalsIgnoreCase("ViewFlipper")) {
					((ViewFlipper) viewTag.view).stopFlipping();
					String cid = ((ViewTag) ((ViewFlipper) viewTag.view).getCurrentView().getTag()).id;
					if (cid.equals(value)) return;
					((ViewFlipper) viewTag.view).showNext();
					while (true) {
						String nid = ((ViewTag) ((ViewFlipper) viewTag.view).getCurrentView().getTag()).id;
						if (nid.equals(value) || nid.equals(cid)) break;
						((ViewFlipper) viewTag.view).showNext();
					}
				} else if (viewTag.type.equalsIgnoreCase("ViewSwitcher")) {
					setChilds(id, value);
				} else if (viewTag.type.equalsIgnoreCase("TextSwitcher")) {
					if (viewTag.style.label_type.equalsIgnoreCase("html")) {
						((TextSwitcher) viewTag.view).setText(Html.fromHtml(value));
					} else if (viewTag.style.label_type.equalsIgnoreCase("string")) {
						((TextSwitcher) viewTag.view).setText(Html.fromHtml(value).toString());
					} else {
						((TextSwitcher) viewTag.view).setText(value);
					}
				} else if (viewTag.type.equalsIgnoreCase("ImageSwitcher")) {
					((ImageSwitcher) viewTag.view).setImageDrawable(RexseeDrawable.getDrawable(mBrowser, value));
					viewTag.style.icon_url = value;
				} else if (viewTag.type.equalsIgnoreCase("VideoView")) {
					int msec = Utilities.getInt(value, 0);
					if (((VideoView) viewTag.view).mediaPlayer != null) ((VideoView) viewTag.view).mediaPlayer.seekTo(msec);
				} else if (viewTag.type.equalsIgnoreCase("WebView") || viewTag.type.equalsIgnoreCase("Browser") || viewTag.type.equalsIgnoreCase("BrowserDiv")) {
					viewTag.style.path = mBrowser.urlListeners.getAbsoluteUrl(value);
					if (value.startsWith(":")) {
						((BrowserDiv) viewTag.view).browser.function.loadHTML(value.substring(1));
					} else {
						((BrowserDiv) viewTag.view).browser.function.load(viewTag.style.path);
					}
				} else if (viewTag.type.equalsIgnoreCase("ListView")) {
					int position = Utilities.getInt(value, 0);
					if (position >= 0) ((ListView) viewTag.view).setSelection(position);
				} else if (viewTag.type.equalsIgnoreCase("GridView")) {
					int position = Utilities.getInt(value, 0);
					if (position >= 0) ((GridView) viewTag.view).setSelection(position);
				} else if (viewTag.type.equalsIgnoreCase("SlidingDrawer")) {
					if (value.equalsIgnoreCase("close")) ((SlidingDrawer) viewTag.view).animateClose();
					else ((SlidingDrawer) viewTag.view).animateOpen();
				} else if (viewTag.type.equalsIgnoreCase("PageView")) {
					int position = Utilities.getInt(value, 0);
					((PageView) viewTag.view).setPageIndex(position);
				} else return;
			}
		});
	}
	public String getValue(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return "";
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return "";
		if (viewTag.type.equalsIgnoreCase("TextView") || viewTag.type.equalsIgnoreCase("EditText")) {
			return ((TextView) viewTag.view).getText().toString();
		} else if (viewTag.type.equalsIgnoreCase("Chronometer")) {
			return ((Chronometer) viewTag.view).getText().toString();
		} else if (viewTag.type.equalsIgnoreCase("ProgressDiv") || viewTag.type.equalsIgnoreCase("Progress")) {
			return getStyle(id, "progress");
		} else if (viewTag.type.equalsIgnoreCase("ToggleButton")) {
			return ((ToggleButton) viewTag.view).isChecked() ? "true" : "false";
		} else if (viewTag.type.equalsIgnoreCase("ProgressBar") || viewTag.type.equalsIgnoreCase("SeekBar")) {
			return String.valueOf(((ProgressBar) viewTag.view).getProgress());
		} else if (viewTag.type.equalsIgnoreCase("RatingBar")) {
			return String.valueOf(((RatingBar) viewTag.view).getRating());
		} else if (viewTag.type.equalsIgnoreCase("RadioGroup")) {
			int rid = ((RadioGroup) viewTag.view).getCheckedRadioButtonId();
			if (rid < 0) return "";
			Set<String> ids = mMap.keySet();
			Iterator<String> iterator = ids.iterator();
			while (iterator.hasNext()) {
				String key = iterator.next();
				if (mMap.get(key).uid == rid) return key;
			}
			return "";
		} else if (viewTag.type.equalsIgnoreCase("CheckBox")) {
			return ((CheckBox) viewTag.view).isChecked() ? "true" : "false";
		} else if (viewTag.type.equalsIgnoreCase("RadioButton")) {
			return ((RadioButton) viewTag.view).isChecked() ? "true" : "false";
		} else if (viewTag.type.equalsIgnoreCase("Spinner")) {
			return String.valueOf(((Spinner) viewTag.view).getSelectedItemPosition());
		} else if (viewTag.type.equalsIgnoreCase("Gallery") || viewTag.type.equalsIgnoreCase("ThreeDGallery")) {
			return String.valueOf(((Gallery) viewTag.view).getSelectedItemPosition());
		} else if (viewTag.type.equalsIgnoreCase("DatePicker")) {
			String rtn = "";
			rtn += "\"year\":" + ((DatePicker) viewTag.view).getYear();
			rtn += ",\"monthOfYear\":" + String.valueOf(((DatePicker) viewTag.view).getMonth() + 1);
			rtn += ",\"dayOfMonth\":" + ((DatePicker) viewTag.view).getDayOfMonth();
			return "{" + rtn + "}";
		} else if (viewTag.type.equalsIgnoreCase("TimePicker")) {
			String rtn = "";
			rtn += "\"hour\":" + ((TimePicker) viewTag.view).getCurrentHour();
			rtn += ",\"minute\":" + ((TimePicker) viewTag.view).getCurrentMinute();
			return "{" + rtn + "}";
		} else if (viewTag.type.equalsIgnoreCase("ViewAnimator")) {
			ViewTag tag = (ViewTag) ((ViewAnimator) viewTag.view).getCurrentView().getTag();
			return (tag == null) ? "" : tag.id;
		} else if (viewTag.type.equalsIgnoreCase("ViewFlipper")) {
			String rtn = "";
			ViewTag tag = (ViewTag) ((ViewFlipper) viewTag.view).getCurrentView().getTag();
			if (tag != null) rtn += "\"current\":" + tag.id;
			rtn += ",\"isFlipping\":" + (((ViewFlipper) viewTag.view).isFlipping() ? "true" : "false");
			return "{" + rtn + "}";
		} else if (viewTag.type.equalsIgnoreCase("ViewSwitcher")) {
			//ViewTag tag = (ViewTag) ((FrameLayout) ((ViewSwitcher) viewTag.view).getCurrentView()).getChildAt(0).getTag();
			//return (tag == null) ? "" : tag.id;
			return (viewTag.childIds.size() > 0) ? viewTag.childIds.get(0) : "";
		} else if (viewTag.type.equalsIgnoreCase("TextSwitcher")) {
			return ((TextView) ((TextSwitcher) viewTag.view).getCurrentView()).getText().toString();
		} else if (viewTag.type.equalsIgnoreCase("ImageSwitcher")) {
			return viewTag.style.icon_url;
		} else if (viewTag.type.equalsIgnoreCase("VideoView")) {
			VideoView view = ((VideoView) viewTag.view);
			String rtn = "";
			rtn += "\"width\":" + view.mediaPlayer.getVideoWidth();
			rtn += ",\"height\":" + view.mediaPlayer.getVideoHeight();
			rtn += ",\"duration\":" + view.mediaPlayer.getDuration();
			rtn += ",\"currentPosition\":" + view.mediaPlayer.getCurrentPosition();
			rtn += ",\"isPlaying\":" + ((view.mediaPlayer.isPlaying()) ? "true" : "false");
			rtn += ",\"isLooping\":" + ((view.mediaPlayer.isLooping()) ? "true" : "false");
			return "{" + rtn + "}";
		} else if (viewTag.type.equalsIgnoreCase("WebView") || viewTag.type.equalsIgnoreCase("Browser") || viewTag.type.equalsIgnoreCase("BrowserDiv")) {
			return viewTag.style.path;
		} else if (viewTag.type.equalsIgnoreCase("ListView")) {
			return String.valueOf(((ListView) viewTag.view).getSelectedItemPosition());
		} else if (viewTag.type.equalsIgnoreCase("GridView")) {
			return String.valueOf(((GridView) viewTag.view).getSelectedItemPosition());
		} else if (viewTag.type.equalsIgnoreCase("SlidingDrawer")) {
			SlidingDrawer view = ((SlidingDrawer) viewTag.view);
			String rtn = "";
			rtn += "\"isOpened\":" + ((view.isOpened()) ? "true" : "false");
			rtn += ",\"isMoving\":" + ((view.isMoving()) ? "true" : "false");
			return "{" + rtn + "}";
		} else if (viewTag.type.equalsIgnoreCase("PageView")) {
			return ((PageView) viewTag.view).getPageTitle();
		} else return "";
	}
	public void start(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return;
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				if (viewTag.type.equalsIgnoreCase("Chronometer")) {
					((Chronometer) viewTag.view).start();
				} else if (viewTag.type.equalsIgnoreCase("ViewFlipper")) {
					((ViewFlipper) viewTag.view).startFlipping();
				} else if (viewTag.type.equalsIgnoreCase("SlidingDrawer")) {
					((SlidingDrawer) viewTag.view).animateOpen();
				} else if (viewTag.type.equalsIgnoreCase("VideoView")) {
					((VideoView) viewTag.view).openVideo();
				}
			}
		});
	}
	public void resume(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return;
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				if (viewTag.type.equalsIgnoreCase("VideoView")) {
					if (((VideoView) viewTag.view).mediaPlayer != null) {
						((VideoView) viewTag.view).mediaPlayer.start();
					}
				}
			}
		});
	}
	public void pause(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return;
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				if (viewTag.type.equalsIgnoreCase("VideoView")) {
					if (((VideoView) viewTag.view).mediaPlayer != null) ((VideoView) viewTag.view).mediaPlayer.pause();
				}
			}
		});
	}
	public void stop(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return;
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				if (viewTag.type.equalsIgnoreCase("Chronometer")) {
					((Chronometer) viewTag.view).stop();
				} else if (viewTag.type.equalsIgnoreCase("ViewFlipper")) {
					((ViewFlipper) viewTag.view).stopFlipping();
				} else if (viewTag.type.equalsIgnoreCase("SlidingDrawer")) {
					((SlidingDrawer) viewTag.view).animateClose();
				} else if (viewTag.type.equalsIgnoreCase("VideoView")) {
					if (((VideoView) viewTag.view).mediaPlayer != null) ((VideoView) viewTag.view).mediaPlayer.stop();
				}
			}
		});
	}

	public void setColumnAttributes(String id, final int columnIndex, final boolean collapsed, final boolean shrinkable, final boolean stretchable) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null || !viewTag.type.equalsIgnoreCase("TableLayout")) return;
		syncRunOnUiThread(new Runnable() {
			@Override
			public void run() {
				if (columnIndex < 0) {
					((TableLayout) viewTag.view).setShrinkAllColumns(shrinkable);
					((TableLayout) viewTag.view).setStretchAllColumns(stretchable);
				} else {
					((TableLayout) viewTag.view).setColumnCollapsed(columnIndex, collapsed);
					((TableLayout) viewTag.view).setColumnShrinkable(columnIndex, shrinkable);
					((TableLayout) viewTag.view).setColumnStretchable(columnIndex, stretchable);
				}
			}
		});
	}
	public String getColumnAttributes(String id, int columnIndex) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return "{}";
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null || !viewTag.type.equalsIgnoreCase("TableLayout")) return "{}";
		TableLayout table = ((TableLayout) viewTag.view);
		String rtn = "";
		rtn += "\"isCollapsed\":" + ((table.isColumnCollapsed(columnIndex)) ? "true" : "false");
		rtn += ",\"isShrinkable\":" + ((table.isColumnShrinkable(columnIndex)) ? "true" : "false");
		rtn += ",\"isStretchable\":" + ((table.isColumnStretchable(columnIndex)) ? "true" : "false");
		rtn += ",\"isAllShrinkable\":" + ((table.isShrinkAllColumns()) ? "true" : "false");
		rtn += ",\"isAllStretchable\":" + ((table.isStretchAllColumns()) ? "true" : "false");
		return "{" + rtn + "}";
	}
	public void setAnimation(String id, String inStyle, String outStyle) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return;
		if (viewTag.type.equalsIgnoreCase("ViewAnimator")
				|| viewTag.type.equalsIgnoreCase("ViewFlipper")
				|| viewTag.type.equalsIgnoreCase("ViewSwitcher")
				|| viewTag.type.equalsIgnoreCase("ImageSwitcher")
				|| viewTag.type.equalsIgnoreCase("TextSwitcher")) {
			try {
				AnimationStyleSheet inSheet = new AnimationStyleSheet(mBrowser).parseStyle(inStyle);
				AnimationStyleSheet outSheet = new AnimationStyleSheet(mBrowser).parseStyle(outStyle);
				inSheet.id = outSheet.id = viewTag.id;
				inSheet.width = outSheet.width = String.valueOf(viewTag.view.getWidth());
				inSheet.height = outSheet.height = String.valueOf(viewTag.view.getHeight());
				((ViewAnimator) viewTag.view).setInAnimation(inSheet.getAnimation());
				((ViewAnimator) viewTag.view).setOutAnimation(outSheet.getAnimation());
			} catch (Exception e) {
				mBrowser.exception(getInterfaceName(), e);
			}
		}

	}

	public void draw(String id, final String commands, boolean anotherThread) {
		draw(id, commands, anotherThread, false);
	}
	public void draw(String id, final String commands, boolean anotherThread, final boolean debug) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null || !viewTag.type.equalsIgnoreCase("SurfaceView")) return;
		viewTag.resumeRunnable = new Runnable() {
			@Override
			public void run() {
				try {
					SurfaceHolder holder = ((SurfaceView) viewTag.view).getHolder();
					Canvas canvas = holder.lockCanvas();
					String[] arr = commands.split("\\|");
					for (int i = 0; i < arr.length; i++) {
						new CanvasSheet(mBrowser.getContext(), arr[i]).draw(canvas, debug);
					}
					holder.unlockCanvasAndPost(canvas);
				} catch (Exception e) {
					//mBrowser.exception(getInterfaceName(), e);
				}
			}
		};
		if (anotherThread && !debug) {
			new Thread(viewTag.resumeRunnable).start();
		} else {
			viewTag.resumeRunnable.run();
		}
	}

	public void startAnimation(String id, final String style) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return;
		AnimationStyleSheet styleSheet = new AnimationStyleSheet(mBrowser).parseStyle(style + ";id:" + id + ";");
		styleSheet.animate(viewTag.view);
	}
	public void stopAnimation(String id) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return;
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null) return;
		((Activity) mContext).runOnUiThread(new Runnable() {
			@Override
			public void run() {
				viewTag.view.clearAnimation();
			}
		});
	}

	public String search(String id, String query) {
		if (id == null || id.trim().equalsIgnoreCase("") || !mMap.containsKey(id)) return "[]";
		final ViewTag viewTag = mMap.get(id);
		if (viewTag == null || viewTag.view == null || !viewTag.type.equalsIgnoreCase("PageView")) return "[]";
		return (query.trim().equals("")) ? ((PageView) viewTag.view).getPageIndexes() : ((PageView) viewTag.view).searchText(query);
	}

}
